package ldh.serialize.type;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import ldh.serialize.BinarySerialized;
import ldh.serialize.Serialized;
import ldh.serialize.io.ByteBuf;
import ldh.serialize.util.SerializedUtil;
import ldh.serialize.util.TransferUtil;

public class IterableSerialized<T> implements BinarySerialized<Iterable<T>> {

	public Serialized<T> serialized;
	
	public boolean isSet = false;
	
	public IterableSerialized(Serialized<T> serialized) {
		this.serialized = serialized;
	}
	
	public IterableSerialized(Serialized<T> serialized, boolean isSet) {
		this.serialized = serialized;
		this.isSet = isSet;
	}
	
	@Override
	public void write(ByteBuf out, Iterable<T> ts) throws IOException {
		if (!(serialized instanceof BinarySerialized)) {
			throw new RuntimeException("serialized is not BinarySerialized");
		}
		BinarySerialized<T> binarySerialized = (BinarySerialized<T>) serialized;
		
		if (ts == null) {
			SerializedUtil.writeByte(out, (byte) 0);
			return;
		}
		SerializedUtil.writeByte(out, (byte) 1);
		Iterator<T> its = ts.iterator();
		int total = 0;
		
		while (its.hasNext()) {
			its.next();
			total++;
		}
		
		out.writeBytes(TransferUtil.intToBytes(total));
		
		its = ts.iterator();
		while (its.hasNext()) {
			T t = its.next();
			binarySerialized.write(out, t);
		}
	}

	@Override
	public Iterable<T> read(ByteBuf in) throws IOException {
		if (!(serialized instanceof BinarySerialized)) {
			throw new RuntimeException("serialized is not BinarySerialized");
		}
		BinarySerialized<T> binarySerialized = (BinarySerialized<T>) serialized;
		byte isNull = SerializedUtil.readByte(in);
		if(isNull < 1) return null;
		
		byte[] bbs = new byte[4];
		in.readBytes(bbs);
		int size = TransferUtil.bytesToInt(bbs, 0);
		if (isSet) {
			Set<T> ts = new HashSet<T>();
			for (int i=0; i<size; i++) {
				T t = binarySerialized.read(in);
				ts.add(t);
			}
			return ts;
			
		} else {
			List<T> ts = new ArrayList<T>();
			for (int i=0; i<size; i++) {
				T t = binarySerialized.read(in);
				ts.add(t);
			}
			return ts;
		}
	}

	@Override
	public Class<Iterable<T>> getClassType() {
		return null;
	}

	public boolean isSet() {
		return this.isSet;
	}

}
